//! \file CoreTask.cpp
//! \brief TODO: Document
// -----------------------------------------------------------------------------
//! This program is free software; you can redistribute it and/or
//! modify it under the terms of the GNU General Public License
//! as published by the Free Software Foundation; either version 2
//! of the License, or (at your option) any later version.
//!
//! This program is distributed in the hope that it will be useful,
//! but WITHOUT ANY WARRANTY; without even the implied warranty of
//! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//! GNU General Public License for more details.
//!
//! You should have received a copy of the GNU General Public License
//! along with this program; if not, write to the Free Software Foundation,
//! Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
// -----------------------------------------------------------------------------
#include "Core.h"
#include <pthread.h>
#include <vector>

namespace Core {

// =====[ Local Definitions ]===================================================

// =====[ Local DataTypes ]=====================================================

// =============================================================================
//! \typedef tThread
//! \brief TODO: document
// -----------------------------------------------------------------------------
typedef pthread_t tThread;

// TODO: document
typedef struct
{
  tThread Thread;
  const tTask *pTask;
} tTaskEntry;

// =====[ Local Variables ]=====================================================
static std::vector<tTaskEntry> Tasks;
//static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

// =====[ Local Implementation ]================================================

// =============================================================================
// Implement: TaskNew
// -----------------------------------------------------------------------------
tERROR TaskNew(const tTask *pTask)
{
//  tThread *pThread;
  tTaskEntry Entry;

//  pthread_mutex_lock(&mutex);

  // Validate our arguments.
  if (pTask == NULL) { return (ERR_INVALID_ARGUMENT); }

  // Retain our user request for later.
  Entry.pTask = pTask;

  // Get our thread started.
  if (pthread_create(&(Entry.Thread), NULL, Entry.pTask->pRoutine, NULL) != 0)
    { return (ERR_UNABLE_TO_CREATE_TASK); }

  // Append the newly created task to the task list.
  Tasks.push_back(Entry);

//  pthread_mutex_unlock(&mutex);

  // Finally, return success.
  return (ERR_NONE);
}


// =============================================================================
// Implement: TaskComplete
// -----------------------------------------------------------------------------
void *TaskComplete(void *pValue)
{
//  pthread_mutex_lock(&mutex);
  pthread_exit(pValue);
//  pthread_mutex_unlock(&mutex);
  return (NULL);
}


// =============================================================================
// Implement: TaskRequestShutdown
// -----------------------------------------------------------------------------
void TaskRequestShutdown(tERROR Error)
{
//  pthread_mutex_lock(&mutex);

  // Iterate through each task and issue the shutdown request.
  for (size_t Index = 0; Index < Tasks.size(); Index++)
  {
    if (Tasks[Index].pTask->pShutdown != NULL)
      { Tasks[Index].pTask->pShutdown(Error); }
  }
//  pthread_mutex_unlock(&mutex);
}


// =============================================================================
// Implement: TaskWaitForShutdown
// -----------------------------------------------------------------------------
void TaskWaitForShutdown(void)
{
  size_t Index;

  void **pExitValue = NULL;

//  pthread_mutex_lock(&mutex);

  // Iterate through each thread and join it.
  for (Index = 0; Index < Tasks.size(); Index++)
  {
    pthread_join(Tasks[Index].Thread, pExitValue);
  }

  // All the task are complete, free the memory?
  Tasks.erase(Tasks.begin(), Tasks.end());
//  pthread_mutex_unlock(&mutex);
}


} // namespace Core
